#include "shrの超强の标准输入&输出库.h"
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>

_FILE _st_stdin = { .fileno = 0, .inbuff_pos = 0 };
_FILE _st_stdout = { .fileno = 1, .outbuff_pos = 0 };
_FILE _st_stderr = { .fileno = 2, .outbuff_pos = 0 };

_FILE* _stdin = &_st_stdin;
_FILE* _stdout = &_st_stdout;
_FILE* _stderr = &_st_stderr;


_FILE* _fopen(const char* filename, const char* flag)
{
  assert(filename && flag);
  int fd = -1;
  if(strcmp(flag, "w") == 0) {
    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  }
  else if(strcmp(flag, "r") == 0) {
    fd = open(filename, O_RDWR);
  }
  else if(strcmp(flag, "a") == 0) {
    fd = open(filename, O_WRONLY | O_CREAT | O_APPEND, 0666);
  }
  else {}
  if(fd < 0) { perror("open err"); exit(1); }
  _FILE* fp = (_FILE*)malloc(sizeof(_FILE));
  if(fp == NULL) { perror("open err"); exit(1); }
  fp->fileno = fd;
  return fp;
}

int _fwrite(const void* buff, int size, int nmem, _FILE* pf)
{
  assert(buff && pf);
  //写入用户缓冲区
  memcpy(pf->outbuff + pf->outbuff_pos, buff, size * nmem); 
  pf->outbuff_pos += size * nmem;
  if(pf->outbuff[pf->outbuff_pos - 1] == '\n')
  {
    ssize_t ret = write(pf->fileno, pf->outbuff, pf->outbuff_pos);
    pf->outbuff_pos = 0;
    return ret;
  }
  if(nmem == 1) { return size; }
  else { return nmem; }
}

int _vsscanf(char* buff, const char* format, va_list argsptr)
{

}

int _scanf(const char* format, ...)
{
  char buff[256];
  va_list args;
  va_start(args, format);
  read(0, buff, sizeof(buff));
  int ret = _vsscanf(buff, format, args);
  return ret;
}

int _vsprintf(char* buff, const char* format, va_list argsptr)
{
  char tmp[256];

  int buffI = 0;
  for(char* p = (char*)format; *p; ++p)
  {
    if(*p != '%') { buff[buffI++] = *p; continue; }
    
    ++p;
    if(*p == 'd')
    {
      sprintf(tmp, "%d", va_arg(argsptr, int));
      strcpy(buff + buffI, tmp);
      buffI += strlen(tmp);
    }
    else if(*p == 's')
    {
      sprintf(tmp, "%s", va_arg(argsptr, char*));
      strcpy(buff + buffI, tmp);
      buffI += strlen(tmp);
    }
    else { /*...*/ }
  }
  buff[buffI] = '\0';
  return buffI; 
}

int _printf(const char *format, ... )
{
  char buff[256];
  va_list args;
  va_start(args, format);
  int ret = _vsprintf(buff, format, args);
  _fwrite(buff, strlen(buff), 1, _stdout);

  return ret;
}

int _fflush(_FILE* pf)
{
  if(pf->outbuff_pos > 0)
  {
    ssize_t ret = write(pf->fileno, pf->outbuff, pf->inbuff_pos); 
    pf->inbuff_pos = 0;
    if(ret < 0) { return EOF; }
  }
  return 1;
}

int _fclose(_FILE* pf)
{
  assert(pf);
  _fflush(pf);
  return close(pf->fileno);
}
